﻿using AutoMapper;
using Mes.Application.Common.Resource;
using Mes.Application.Common;
using Mes.Application.DTO.Inputs.Quality;
using Mes.Application.DTO.Results.Quality;
using Mes.Domain.BoundedContext.Entities.Quality;
using Mes.Domain.BoundedContext;
using Mes.Infrastructure.Data.BoundedContext.Repositories.Quality;
using System.Linq.Expressions;
using Mes.Infrastructure.Data.BoundedContext.Extensions;
using Mes.Infrastructure.Data.BoundedContext.Repositories.MasterData;
using Microsoft.EntityFrameworkCore;

namespace Mes.Application.Services.Quality
{
    public class CharacteristicService : ICharacteristicService
    {
        private readonly IMapper _mapper;
        private readonly ICharacteristicRepository _characteristicRepository;
        private readonly IMeasuringUnitRepository _measuringUnitRepository;
        private readonly IQmSpecCharLinkRepository _qmSpecCharLinkRepository;
        private readonly IProductionUnitRepository _productionUnitRepository;
        public CharacteristicService(IMapper mapper, ICharacteristicRepository characteristicRepository, IMeasuringUnitRepository measuringUnitRepository,IQmSpecCharLinkRepository qmSpecCharLinkRepository, IProductionUnitRepository productionUnitRepository)
        {
            if (mapper == null || characteristicRepository == null)
            {
                throw new ArgumentNullException();
            }
            _mapper = mapper;
            _characteristicRepository = characteristicRepository;
            _measuringUnitRepository = measuringUnitRepository;
            _qmSpecCharLinkRepository = qmSpecCharLinkRepository;
            _productionUnitRepository = productionUnitRepository;
        }

        /// <summary>
        /// 添加质量特征
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task AddCharacteristicAsync(AddingCharacteristicInput input)
        {
            //质量特征名称不能重复
            if (await _characteristicRepository.ExistsAsync(x => x.Char_Name == input.Char_Name))
            {
                throw new CustomException(Messages.CharacteristicNameMustBeUnique);
            }
            //质量特征仅仅包含计量属性和计数属性两种类型
            if (input.Type != 0 && input.Type != 1)
            {
                throw new CustomException(Messages.CharacteristicContainMeteringAndCountingAttributes);
            }
            /// 计量属性 2 = 均值-极差控制图（xBar-R图）
            ///         3 = 均值-标准差控制图（xBar-S图）
            ///         7  = 中位数-极差控制图（x-R图）
            ///         5  = 单值-移动极差控制图（x-MR图）
            if (input.Type == 0)
            {
                var meteringCharts = new List<int>() { 2, 3, 7, 5 };
                if (!meteringCharts.Any(x => x == input.Default_Chart))
                {
                    throw new CustomException(Messages.DefautChartIsNotMetering);
                }
            }
            /// 计数属性 16 = P图
            ///         17 = NP图
            ///         18 = U图
            ///         19 = C图
            if (input.Type == 1)
            {
                var countingCharts = new List<int>() { 16, 17, 18, 19 };
                if (!countingCharts.Any(x => x == input.Default_Chart))
                {
                    throw new CustomException(Messages.DefautChartIsNotCounting);
                }
            }
            //验证单位是否存在
            if (!await _measuringUnitRepository.ExistsAsync(x => x.Id == input.Uom_Id))
            {
                throw new CustomException(Messages.MeasuringUnitNotFound);
            }
            //验证最大样本大小>=标准样本大小>=最小样本大小
            if (input.Maximum_Sample_Size != null)
            {
                if (input.Maximum_Sample_Size < input.Minimum_Sample_Size)
                {
                    throw new CustomException(Messages.MaximumSampleSizeCannotLessThenMinimumSampleSize);
                }
                if (input.Maximum_Sample_Size < input.Normal_Sample_Size)
                {
                    throw new CustomException(Messages.MaximumSampleSizeCannotLessThenNormalSampleSize);
                }
            }
            if (input.Normal_Sample_Size < input.Minimum_Sample_Size)
            {
                throw new CustomException(Messages.NormalSampleSizeCannotLessThenMinimumSampleSize);
            }

            var characteristic = _mapper.Map<Characteristic>(input);
            await _characteristicRepository.AddAsync(characteristic);
            int status = await _characteristicRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 删除质量特征
        /// </summary>
        /// <param name="char_id">质量特征Id</param>
        /// <returns></returns>
        public async Task DeleteCharacteristicAsync(int char_id)
        {
            await _characteristicRepository.DeleteAsync(x => x.Char_Id == char_id);
            int status = await _characteristicRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.ErrorSavingOper);
            }
        }

        /// <summary>
        /// 编辑质量特征
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task UpdateCharacteristicAsync(UpdatingCharacteristicInput input)
        {
            var characteristic = await _characteristicRepository.FindAsync(x => x.Char_Id == input.Char_Id);
            if (characteristic == null)
            {
                throw new CustomException(Messages.CharacteristicNotFound);
            }
            //质量特征名称不能重复
            if (await _characteristicRepository.ExistsAsync(x => x.Char_Name == input.Char_Name && x.Char_Id != input.Char_Id))
            {
                throw new CustomException(Messages.CharacteristicNameMustBeUnique);
            }
            //质量特征仅仅包含计量属性和计数属性两种类型
            if (input.Type != 0 && input.Type != 1)
            {
                throw new CustomException(Messages.CharacteristicContainMeteringAndCountingAttributes);
            }
            /// 计量属性 2 = 均值-极差控制图（xBar-R图）
            ///         3 = 均值-标准差控制图（xBar-S图）
            ///         7 = 中位数-极差控制图（x-R图）
            ///         5 = 单值-移动极差控制图（x-MR图）
            if (input.Type == 0)
            {
                var meteringCharts = new List<int>() { 2, 3, 7, 5 };
                if (!meteringCharts.Any(x => x == input.Default_Chart))
                {
                    throw new CustomException(Messages.DefautChartIsNotMetering);
                }
            }
            /// 计数属性 16 = P图
            ///         17 = NP图
            ///         18 = U图
            ///         19 = C图
            if (input.Type == 1)
            {
                var countingCharts = new List<int>() { 16, 17, 18, 19 };
                if (!countingCharts.Any(x => x == input.Default_Chart))
                {
                    throw new CustomException(Messages.DefautChartIsNotCounting);
                }
            }
            //验证单位是否存在
            if (!await _measuringUnitRepository.ExistsAsync(x => x.Id == input.Uom_Id))
            {
                throw new CustomException(Messages.MeasuringUnitNotFound);
            }
            //验证最大样本大小>=标准样本大小>=最小样本大小
            if (input.Maximum_Sample_Size != null)
            {
                if (input.Maximum_Sample_Size < input.Minimum_Sample_Size)
                {
                    throw new CustomException(Messages.MaximumSampleSizeCannotLessThenMinimumSampleSize);
                }
                if (input.Maximum_Sample_Size < input.Normal_Sample_Size)
                {
                    throw new CustomException(Messages.MaximumSampleSizeCannotLessThenNormalSampleSize);
                }
            }
            if (input.Normal_Sample_Size < input.Minimum_Sample_Size)
            {
                throw new CustomException(Messages.NormalSampleSizeCannotLessThenMinimumSampleSize);
            }
            characteristic.Char_Name = input.Char_Name;
            characteristic.Char_Desc = input.Char_Desc;
            characteristic.Type = input.Type;
            characteristic.Uom_Id = input.Uom_Id;
            characteristic.Default_Chart = input.Default_Chart;
            characteristic.Num_Decimals = input.Num_Decimals;
            characteristic.Normal_Sample_Size = input.Normal_Sample_Size;
            characteristic.Minimum_Sample_Size = input.Minimum_Sample_Size;
            characteristic.Maximum_Sample_Size = input.Maximum_Sample_Size;
            characteristic.Automated_Coll = input.Automated_Coll;
            characteristic.Time_Interval = input.Time_Interval;
            characteristic.Time_Int_Unit = input.Time_Int_Unit;
            characteristic.Last_Edit_At = DateTime.Now;
            var status = await _characteristicRepository.SaveAsync();
            if (status <= 0)
            {
                throw new CustomException(Messages.SavingFailure);
            }
        }

        /// <summary>
        /// 查询质量特征实体
        /// </summary>
        /// <param name="char_id">质量特征Id</param>
        /// <returns></returns>
        public async Task<CharacteristicDetailResult> GetCharacteristicAsync(int char_id)
        {
            var characteristic = await _characteristicRepository.FindAsync(x => x.Char_Id == char_id);
            if (characteristic == null)
            {
                throw new CustomException(Messages.CharacteristicNotFound);
            }
            var data = _mapper.Map<CharacteristicDetailResult>(characteristic);
            //查询单位
            var uom = await _measuringUnitRepository.FindAsync(x => x.Id == data.Uom_Id);
            data.Uom_Name = uom?.UnitName ?? String.Empty;
            return data;
        }

        /// <summary>
        /// 查询质量特征分页列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedItemsData<CharacteristicResult>> GetCharacteristicsAsync(GettingCharacteristicsInput input)
        {
            Expression<Func<Characteristic, bool>> filter = x => true;
            if (!string.IsNullOrEmpty(input.KeyWord))
            {
                filter = filter.And(x => x.Char_Name.Contains(input.KeyWord) || x.Char_Desc.Contains(input.KeyWord));
            }
            var chars = await _characteristicRepository.Query().Where(filter).OrderByDescending(x => x.Char_Id).ToPagedAsync(input.PagedInput);
            var data = _mapper.Map<PagedItemsData<CharacteristicResult>>(chars);
            //查询每个质量特征的单位
            var uomIds = data.Items.Select(x => x.Uom_Id).Distinct().ToList();
            if (uomIds.Count > 0)
            {
                var uoms = await _measuringUnitRepository.Query().Where(x => uomIds.Contains(x.Id)).ToListAsync();
                foreach (var item in data.Items)
                {
                    item.Uom_Name = uoms.FirstOrDefault(x => x.Id == item.Uom_Id)?.UnitName ?? String.Empty;
                }
            }
            return data;
        }

        /// <summary>
        /// 根据质量规格ID列表获取关联的质量特征
        /// </summary>
        /// <param name="qm_spec_id_list">质量规则ID列表，以，分隔</param>
        /// <returns></returns>
        public async Task<ItemsResult<CharacteristicResultForQmSpec>> GetCharacteristicForQmSpecAsync(string? qm_spec_id_list)
        {
            var intSpecIds = new List<int>();
            var chars = new List<Characteristic>();
            if (!string.IsNullOrEmpty(qm_spec_id_list))
            {
                var specIds = qm_spec_id_list.Split(",").ToList();
                foreach (var item in specIds)
                {
                    intSpecIds.Add(int.TryParse(item, out int result) ? result : 0);
                }
                var links = await _qmSpecCharLinkRepository.Query().Where(x => intSpecIds.Contains(x.Qm_Spec_Id)).ToListAsync();
                var charIds = links.Select(x => x.Char_Id).Distinct().ToList();
                chars = await _characteristicRepository.Query().Where(x => charIds.Contains(x.Char_Id)).OrderBy(x=>x.Char_Id).ToListAsync();
            }
            else
            {
                chars = await _characteristicRepository.Query().OrderBy(x => x.Char_Id).ToListAsync();
            }
            var data = _mapper.Map<List<CharacteristicResultForQmSpec>>(chars);
            var uomIds = data.Select(x => x.Uom_Id).Distinct().ToList();
            var uoms = await _measuringUnitRepository.Query().Where(x => uomIds.Contains(x.Id)).ToListAsync();
            foreach (var item in data)
            {
                item.Uom_Desc = uoms.FirstOrDefault(x => x.Id == item.Uom_Id)?.UnitName ?? String.Empty;
                item.Default_Chart_Desc = item.Default_Chart switch
                {
                    2 => "Xbar + Range",
                    3 => "Xbar + Sigma",
                    5 => "IX + MR",
                    7 => "MA + Range",
                    8 => "MA + Sigma",
                    16 => "p",
                    17 => "np",
                    18 => "u",
                    19 => "c",
                    20 => "DPMO",
                    _ => "Xbar + Range",
                };
                item.Type_Desc = item.Type switch
                {
                    0 => "计量属性",
                    1 => "计数属性",
                    _ => "计量属性",
                };
                item.Automated_Coll_Desc = item.Automated_Coll ? "Yes" : "No";
                item.Time_Int_Unit_Desc = item.Time_Int_Unit switch
                {
                    0 => "Seconds",
                    1 => "Minutes",
                    2 => "Hours",
                    _ => "Seconds",
                };
                item.Sample_Size_Source_Desc = item.Sample_Size_Source switch
                {
                    0 => "Fixed",
                    1 => "Entered",
                    2 => "Copied from the previous value",
                    3 => "Obtained from a sample size characteristic",
                    _ => "Fixed",
                };
            }
            return new ItemsResult<CharacteristicResultForQmSpec> { Items = data };
        }
    }
}
